package com.tools.web.filter.gateway;

import com.tools.common.container.ConcurrentHashSet;
import com.tools.common.object.Note;

import java.util.HashSet;
import java.util.Set;

/**
 * 用本地缓存实现的网管过滤器的部分公共逻辑的抽象实现
 * */
@Note("用本地缓存实现的网管过滤器的部分公共逻辑的抽象实现")
public abstract class AbsLocalCacheGetawayFilter extends GetawayFilter {

    @Note("代理服务器 IP 白名单容器")
    private ConcurrentHashSet<String> proxyWhiteSet;

    @Note("已禁用的接口列表容器")
    private ConcurrentHashSet<String> disabledURISet;

    @Note("客户端 IP 白名单容器")
    private ConcurrentHashSet<String> ipWhiteSet;

    @Note("客户端 IP 黑名单容器")
    private ConcurrentHashSet<String> ipBlackSet;

    @Note("是否关闭代理服务器白名单功能，让所有请求可以绕过代理直接请求服务器。默认关闭")
    private boolean openAllRequest = false;

    @Note("是否封闭服务器的所有接口，阻止所有请求访问。默认关闭")
    private boolean disabledAllURI = false;

    @Note("是否允许所有的客户端 IP 对服务进行请求。默认关闭")
    private boolean allowAllIPRequest = false;

    @Note("是否禁止所有的客户端 IP 对服务进行请求。默认关闭")
    private boolean denyAllIPRequest = false;


    protected AbsLocalCacheGetawayFilter(GetawaySource source, boolean mustTrueCondition, String errorMessage) {
        super(source, mustTrueCondition, errorMessage);
        if(this.proxyIsEnabled()) this.proxyWhiteSet = new ConcurrentHashSet<>();
        if(this.disabledURIIsEnabled()) this.disabledURISet = new ConcurrentHashSet<>();
        if(this.ipWhitesIsEnabled()) this.ipWhiteSet = new ConcurrentHashSet<>();
        if(this.ipBlacksIsEnabled()) this.ipBlackSet = new ConcurrentHashSet<>();
    }

    @Override
    protected void protected_putInitProxyWhitesData(Set<String> proxyIps) {
        for (String remoteAddr : proxyIps) {
            if(remoteAddr != null && !remoteAddr.isEmpty()) this.proxyWhiteSet.add(remoteAddr);
        }
    }

    @Override
    protected void protected_putInitDisabledURIData(Set<String> disabledURIs) {
        for (String uri : disabledURIs) {
            if(uri != null && !uri.isEmpty()) this.disabledURISet.add(uri);
        }
    }

    @Override
    protected void protected_putInitIPWhitesData(Set<String> ipWhites) {
        for (String clientIP : ipWhites) {
            if(clientIP != null && !clientIP.isEmpty()) this.ipWhiteSet.add(clientIP);
        }
    }

    @Override
    protected void protected_putInitIPBlacksData(Set<String> ipBlacks) {
        for (String clientIP : ipBlacks) {
            if(clientIP != null && !clientIP.isEmpty()) this.ipBlackSet.add(clientIP);
        }
    }

    @Override
    public boolean isInProxyWhites(String remoteAddr) {
        return openAllRequest || this.proxyWhiteSet.contains(remoteAddr);
    }

    @Override
    public boolean isDisabledURI(String uri) {
        return disabledAllURI || this.disabledURISet.contains(uri);
    }

    @Override
    public boolean isWhitesIP(String clientIP) {
        return allowAllIPRequest || this.ipWhiteSet.contains(clientIP);
    }

    @Override
    public boolean isBlacksIP(String clientIP) {
        return denyAllIPRequest || this.ipBlackSet.contains(clientIP);
    }

    @Override
    public void addInProxyIPs(String remoteAddr) {
        if(!proxyIsEnabled()) return;
        boolean result = private_add(this.proxyWhiteSet, remoteAddr);
        if(result) this.openAllRequest = true;
    }

    @Override
    public void removeFromProxyIPs(String remoteAddr) {
        if(!proxyIsEnabled()) return;
        boolean result = private_remove(this.proxyWhiteSet, remoteAddr);
        if(result) this.openAllRequest = false;
    }

    @Override
    public void clearProxyIPs() {
        if(!proxyIsEnabled()) return;
        this.proxyWhiteSet.clear();
    }

    @Override
    public Set<String> copyProxyIPs() {
        if(!proxyIsEnabled()) return new HashSet<>();
        return new HashSet<>(this.proxyWhiteSet);
    }

    @Override
    public boolean proxyIPsIsEmpty() {
        return !proxyIsEnabled() || this.proxyWhiteSet.isEmpty();
    }

    @Override
    public void debugProxyIPs() {
        this.protected_logPrintInitDataList(this.protected_getLogger(), this.copyProxyIPs(), "代理服务器 IP 白名单");
    }

    @Override
    public void addInDisabledURIs(String uri) {
        if(!disabledURIIsEnabled()) return;
        boolean result = private_add(this.disabledURISet, uri);
        if(result) this.disabledAllURI = true;
    }

    @Override
    public void removeFromDisabledURIs(String uri) {
        if(!disabledURIIsEnabled()) return;
        boolean result = private_remove(this.proxyWhiteSet, uri);
        if(result) this.disabledAllURI = false;
    }

    @Override
    public void clearDisabledURIs() {
        if(!disabledURIIsEnabled()) return;
        this.disabledURISet.clear();
    }

    @Override
    public Set<String> copyDisabledURIs() {
        if(!disabledURIIsEnabled()) return new HashSet<>();
        return new HashSet<>(this.disabledURISet);
    }

    @Override
    public boolean disabledURIsIsEmpty() {
        return !disabledURIIsEnabled() || this.disabledURISet.isEmpty();
    }

    @Override
    public void debugDisabledURIs() {
        this.protected_logPrintInitDataList(this.protected_getLogger(), this.copyDisabledURIs(), "已禁用的接口列表");
    }

    @Override
    public void addInWhites(String clientIP) {
        if(!ipWhitesIsEnabled()) return;
        boolean result = private_add(this.ipWhiteSet, clientIP);
        if(result) this.allowAllIPRequest = true;
    }

    @Override
    public void removeFromWhites(String clientIP) {
        if(!ipWhitesIsEnabled()) return;
        boolean result = private_remove(this.ipWhiteSet, clientIP);
        if(result) this.allowAllIPRequest = false;
    }

    @Override
    public void clearWhites() {
        if(!ipWhitesIsEnabled()) return;
        this.ipWhiteSet.clear();
    }

    @Override
    public Set<String> copyWhites() {
        if(!ipWhitesIsEnabled()) return new HashSet<>();
        return new HashSet<>(this.ipWhiteSet);
    }

    @Override
    public boolean ipWhitesIsEmpty() {
        return !ipWhitesIsEnabled() || this.ipWhiteSet.isEmpty();
    }

    @Override
    public void debugIPWhites() {
        this.protected_logPrintInitDataList(this.protected_getLogger(), this.copyWhites(), "客户端 IP 白名单");
    }

    @Override
    public void addInBlacks(String clientIP) {
        if(!ipBlacksIsEnabled()) return;
        boolean result = private_add(this.ipBlackSet, clientIP);
        if(result) this.denyAllIPRequest = true;
    }

    @Override
    public void removeFromBlacks(String clientIP) {
        if(!ipBlacksIsEnabled()) return;
        boolean result = private_remove(this.ipBlackSet, clientIP);
        if(result) this.denyAllIPRequest = false;
    }

    @Override
    public void clearBlacks() {
        if(!ipBlacksIsEnabled()) return;
        this.ipBlackSet.clear();
    }

    @Override
    public Set<String> copyBlacks() {
        if(!ipBlacksIsEnabled()) return new HashSet<>();
        return new HashSet<>(this.ipBlackSet);
    }

    @Override
    public boolean ipBlacksIsEmpty() {
        return !ipBlacksIsEnabled() || this.ipBlackSet.isEmpty();
    }

    @Override
    public void debugIPBlacks() {
        this.protected_logPrintInitDataList(this.protected_getLogger(), this.copyBlacks(), "客户端 IP 黑名单");
    }


    @Note("判断添加的内容是否是影响全局的通配符，如果是则修改全局的属性为 true")
    private boolean private_add(Set<String> dataSet, String data) {
        if("*".equals(data)) {
            return true;
        }
        if(data != null && !data.isEmpty()) {
            dataSet.add(data);
        }
        return false;
    }

    @Note("判断移除的内容是否是影响全局的通配符，如果是则修改全局的属性为 false")
    private boolean private_remove(Set<String> dataSet, String data) {
        if("*".equals(data)) {
            return true;
        }
        dataSet.remove(data);
        return false;
    }
}
